﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Diagnostics;

namespace GenerateurMusique
{
    class individu
    {
        public int[] notes = new int[20];
        public int instrument;
        string strFileName;
        
     
        public individu(int instrument,int[] notes)
        {
            this.instrument = instrument;
            this.notes = notes;
        }
       
       public individu(individu parent,double mutation)
        {
         
           this.instrument=parent.instrument;
           this.notes=parent.notes;
            Random rand = new Random();
           if(rand.Next(0,101)<mutation*100){
            mutationinstrument(rand);
           }
            for(int i=0;i<20;i++){
                if (rand.Next(0, 101) < mutation * 100)
                {
                    mutationnote(rand, i);
                }
            }
        }
        public individu(individu parent1,individu parent2,double crossover,double mutation)
        {
            Random rand = new Random();
            int choix=rand.Next(0, 2);
            if (choix == 0)
            {
                this.instrument = parent1.instrument;
            }
            else
            {
                this.instrument = parent2.instrument;
            }
            int taux = (int)Math.Ceiling(crossover * 20);
            for (int i = 0; i < 20; i++)
            {
                if (i <= taux)
                {
                    this.notes[i] = parent1.notes[i];
                }
                else
                {
                    this.notes[i] = parent2.notes[i];
                }
              
                if (rand.Next(0, 101) < mutation * 100)
                {
                    mutationnote(rand, i);
                }
            }
            if (rand.Next(0, 101) < mutation * 100)
            {
                mutationinstrument(rand);
            }
        }

       
        
        void mutationinstrument(Random rand)
        {
            int testmutation = rand.Next(0, 10);
            if (testmutation == 9)
            {
                instrument =rand.Next(1, 129);

                if (instrument < 1)
                {
                    instrument = 1;
                }
                else if (instrument > 128)
                {
                    instrument = 128;
                }
            }
        }

        void mutationnote(Random rand,int position )
        {
          
            int testpositif = rand.Next(0, 2);
            if (testpositif == 0)
            {
                testpositif = -1;
            }
            int testmutation = rand.Next(0, 10);
            if (testmutation == 9)
            {
                notes[position] = notes[position] + testpositif*rand.Next(1, 11);

                if (notes[position] < 0)
                {
                    notes[position] = 0;
                }
                else if (notes[position] > 127)
                {
                    notes[position] = 127;
                }
            }
        }
        public void CreateAndPlayMusic(int nbFile)
        {
            // s'il y a un fichier en cours de lecture on l'arrête 
        
            
            // Générateur aléatoire
            Random rand = new Random();

            // 1) Créer le fichier MIDI
            // a. Créer un fichier et une piste audio ainsi que les informations de tempo
            MIDISong song = new MIDISong();
            song.AddTrack("Piste1");
            song.SetTimeSignature(0, 4, 4);
            song.SetTempo(0, 150);

            // b. Choisir un instrument entre 1 et 128 
            // Liste complète ici : http://fr.wikipedia.org/wiki/General_MIDI
            
            song.SetChannelInstrument(0, 0, this.instrument);

            // c. Ajouter des notes
            // Chaque note est comprise entre 0 et 127 (12 correspond au type de note, fixe ici à des 1/4)
            // L'équivalence avec les notes / octaves est disponible ici : https://andymurkin.files.wordpress.com/2012/01/midi-int-midi-note-no-chart.jpg
            // Ici 16 notes aléatoire entre 16 et 96 (pour éviter certaines notes trop aigues ou trop graves)
            for (int i = 0; i < 20; i++)
            {
                
                song.AddNote(0, 0, this.notes[i], 12);
            }

            // d. Enregistrer le fichier .mid (lisible dans un lecteur externe par exemple)
            // on prépare le flux de sortie
            MemoryStream ms = new MemoryStream();
            song.Save(ms);
            ms.Seek(0, SeekOrigin.Begin);
            byte[] src = ms.GetBuffer();
            byte[] dst = new byte[src.Length];
            for (int i = 0; i < src.Length; i++)
            {
                dst[i] = src[i];
            }
            ms.Close();
            // et on écrit le fichier
            strFileName = "Fichier" + nbFile + ".mid";
            FileStream objWriter = File.Create(strFileName);
            objWriter.Write(dst, 0, dst.Length);
            objWriter.Close();
            objWriter.Dispose();
            objWriter = null;

           
        }
    }
}
